/////////////////////////////////////////////////////////////////////////////
// Name:        toolbarcust.h
// Purpose:     Classes for allowing the user to customise toolbars.
// Author:      Julian Smart
// Modified by:
// Created:     2006-11-28
// RCS-ID:      $Id: toolbarcust.h,v 1.1 2007/11/05 12:51:03 anthemion Exp $
// Copyright:   (c) Julian Smart
// Licence:     New BSD License
/////////////////////////////////////////////////////////////////////////////

#ifndef _WX_TOOLBARCUST_H_
#define _WX_TOOLBARCUST_H_

#include "wx/toolbar.h"
#include "wx/confbase.h"

/*!
 * wxToolBarCustomisationInfoItem stores customisation information about a single tool.
 */

class wxToolBarCustomisationInfoItem: public wxObject
{
public:
    wxToolBarCustomisationInfoItem();
    wxToolBarCustomisationInfoItem(const wxToolBarCustomisationInfoItem& item);
    ~wxToolBarCustomisationInfoItem();

    void Copy(const wxToolBarCustomisationInfoItem& item);

    // style
    bool IsButton() const { return m_toolStyle == wxTOOL_STYLE_BUTTON; }
    bool IsControl() const { return m_toolStyle == wxTOOL_STYLE_CONTROL; }
    bool IsSeparator() const { return m_toolStyle == wxTOOL_STYLE_SEPARATOR; }
    int GetStyle() const { return m_toolStyle; }
    int GetId() const { return m_id; }
    wxItemKind GetKind() const
    {
        wxASSERT_MSG( IsButton(), _T("only makes sense for buttons") );

        return m_kind;
    }

    // state
    wxToolBarCustomisationInfoItem& Enable(bool enable) { m_enabled = enable; return *this; }
    bool IsEnabled() const { return m_enabled; }

    bool CanBeToggled() const
        { return m_kind == wxITEM_CHECK || m_kind == wxITEM_RADIO; }

    // attributes
    const wxBitmap& GetNormalBitmap() const { return m_bmpNormal; }
    const wxBitmap& GetDisabledBitmap() const { return m_bmpDisabled; }

    wxToolBarCustomisationInfoItem& SetLabel(const wxString& label) { m_label = label; return *this; }
    const wxString& GetLabel() const { return m_label; }

    wxToolBarCustomisationInfoItem& SetName(const wxString& name) { m_name = name; return *this; }
    const wxString& GetName() const { return m_name; }

    const wxString& GetShortHelp() const { return m_shortHelpString; }
    const wxString& GetLongHelp() const { return m_longHelpString; }

    wxToolBarCustomisationInfoItem& SetShortHelp(const wxString& help) { m_shortHelpString = help; return *this; }
    wxToolBarCustomisationInfoItem& SetLongHelp(const wxString& help) { m_longHelpString = help; return *this; }

    wxToolBarCustomisationInfoItem& SetNormalBitmap(const wxBitmap& bmp) { m_bmpNormal = bmp; return *this; }
    wxToolBarCustomisationInfoItem& SetDisabledBitmap(const wxBitmap& bmp) { m_bmpDisabled = bmp; return *this; }

    // tool parameters
    int                     m_toolStyle;    // see enum wxToolBarToolStyle
    int                     m_id;           // the tool id, wxID_SEPARATOR for separator
    wxItemKind              m_kind;         // for normal buttons may be wxITEM_NORMAL/CHECK/RADIO

    // Whether user-enabled
    bool                    m_enabled;

    // normal and disabled bitmaps for the tool, both can be invalid
    wxBitmap                m_bmpNormal;
    wxBitmap                m_bmpDisabled;

    // the button label
    wxString                m_label;

    // the name of the item, for referencing by the app
    wxString                m_name;

    // short and long help strings
    wxString                m_shortHelpString;
    wxString                m_longHelpString;
};

/*!
 * wxToolBarCustomisationInfo stores customisation information about a single toolbar.
 */

class wxToolBarCustomisationInfo: public wxObject
{
public:
    wxToolBarCustomisationInfo(const wxString& toolbarName = wxEmptyString);
    wxToolBarCustomisationInfo(const wxToolBarCustomisationInfo& info);
    ~wxToolBarCustomisationInfo();

    /// Initialises the class
    void Init();

    /// Clears the items
    void Clear();

    /// Copies the object
    void Copy(const wxToolBarCustomisationInfo& info);

    /// Adds a tool
    wxToolBarCustomisationInfoItem& AddTool(int toolid, const wxString& name,
                const wxString& label,
                const wxBitmap& bitmap,
                const wxBitmap& bmpDisabled,
                wxItemKind kind = wxITEM_NORMAL,
                const wxString& shortHelp = wxEmptyString,
                const wxString& longHelp = wxEmptyString,
                int style = wxTOOL_STYLE_BUTTON);

    /// Adds a normal button tool
    wxToolBarCustomisationInfoItem& AddButton(int toolid, const wxString& name,
                const wxString& label,
                const wxBitmap& bitmap,
                const wxString& shortHelp = wxEmptyString,
                const wxString& longHelp = wxEmptyString);

    /// Adds a check button tool
    wxToolBarCustomisationInfoItem& AddCheckButton(int toolid, const wxString& name,
                const wxString& label,
                const wxBitmap& bitmap,
                const wxString& shortHelp = wxEmptyString,
                const wxString& longHelp = wxEmptyString);

    /// Adds a radio button tool
    wxToolBarCustomisationInfoItem& AddRadioButton(int toolid, const wxString& name,
                const wxString& label,
                const wxBitmap& bitmap,
                const wxString& shortHelp = wxEmptyString,
                const wxString& longHelp = wxEmptyString);

    /// Adds a control
    wxToolBarCustomisationInfoItem& AddControl(int toolid, const wxString& name,
                const wxString& shortHelp = wxEmptyString,
                const wxString& longHelp = wxEmptyString);

    /// Adds a separator
    wxToolBarCustomisationInfoItem& AddSeparator();

    /// Saves enabled status to config
    bool Save(const wxString& path, wxConfigBase& config);

    /// Load enabled status from config
    bool Load(const wxString& path, wxConfigBase& config);

/// To be used when iterating through items. Only iterates through enabled items

    /// Reset to beginning of info, to be called before iterating
    bool Reset(wxToolBarBase* toolBar);

    /// Call at the beginning of the loop
    bool GetNextItem();

    /// Creates a tool using the current info. Also implicitly creates a separator
    /// if appropriate.
    bool CreateTool();

    /// Creates a tool using the current info. Also implicitly creates a separator
    /// if appropriate.
    bool CreateTool(wxControl* control);

    /// Gets the current item
    const wxToolBarCustomisationInfoItem& GetCurrentItem() const;
    wxToolBarCustomisationInfoItem& GetCurrentItem() ;

    /// True if the current tool is a control
    bool IsControl() const;

    /// True if the current tool is a separator
    bool IsSeparator() const;

    /// True if the current tool is a button
    bool IsButton() const;

    /// True if the current tool is enabled
    bool IsEnabled() const;

//// Accessors

    /// Get/set toolbar enabled flag
    bool IsToolBarEnabled() const { return m_toolbarEnabled; }
    void SetToolBarEnabled(bool enabled) { m_toolbarEnabled = enabled; }

    /// Get/set can have labels
    bool GetCanHaveLabels() const { return m_canHaveLabels; }
    void SetCanHaveLabels(bool labels) { m_canHaveLabels = labels; }

    /// Get/set labels
    bool GetUseLabels() const { return m_useLabels; }
    void SetUseLabels(bool useLabels) { m_useLabels = useLabels; }

    /// Get total number of items
    int GetTotalItemCount() const;

    /// Get number of enabled items
    int GetEnabledItemCount() const;

    /// Gets the nth item
    const wxToolBarCustomisationInfoItem& GetItem(int n) const;
    wxToolBarCustomisationInfoItem& GetItem(int n) ;

    /// Finds a tool by name
    wxToolBarCustomisationInfoItem* Find(const wxString& name) const;

    /// Finds a tool by id
    wxToolBarCustomisationInfoItem* Find(int id) const;

    /// Set/get name
    void SetName(const wxString& name) { m_name = name; }
    const wxString& GetName() const { return m_name; }

/// Implementation

   /// Returns the key with "prefix/" prepended if non-empty
    wxString GetKey(const wxString& prefix, const wxString& key) const;

protected:
    wxString        m_name;
    wxList          m_toolbarItems;
    int             m_currentTool;
    bool            m_needsSeparator;
    int             m_createdCount;
    bool            m_toolbarEnabled;
    bool            m_canHaveLabels;
    bool            m_useLabels;
    wxToolBarBase*  m_currentToolBar;
};

/*!
 * wxToolBarCustomisationManager manages multiple customisation information.
 */

class wxToolBarCustomisationManager: public wxObject
{
public:
    wxToolBarCustomisationManager();
    ~wxToolBarCustomisationManager();

    /// Initialises the class
    void Init();

    /// Clears the items
    void Clear();

    /// Adds information about a toolbar
    void Add(wxToolBarCustomisationInfo* info);

    /// Finds information about a toolbar
    wxToolBarCustomisationInfo* Find(const wxString& name) const;

    /// Finds the nth info for the given name
    int FindIndex(const wxString& name) const;

    /// Gets the nth record
    wxToolBarCustomisationInfo* GetNth(int n) const;

    /// Gets the number of toolbar customisation records
    int GetCount() const { return m_infos.GetCount(); }

    /// Saves enabled status to config
    bool Save(const wxString& path, wxConfigBase& config);

    /// Load enabled status from config
    bool Load(const wxString& path, wxConfigBase& config);

protected:

    wxList          m_infos;
};

/*!
 * A toolbar that sends an event to itself when requesting customisation
 */

#define wxID_CUSTOMIZE_TOOLBAR  wxID_HIGHEST + 1

class wxCustomisableToolBar: public wxToolBar
{
    DECLARE_CLASS(wxCustomisableToolBar)
    DECLARE_EVENT_TABLE()
public:

    wxCustomisableToolBar()
    {
        Init();
    }

    wxCustomisableToolBar(wxWindow* parent, wxWindowID id, const wxPoint& pos = wxDefaultPosition, const wxSize& sz = wxDefaultSize,
        long style = wxTB_FLAT|wxTB_HORIZONTAL|wxTB_NODIVIDER|wxTB_NOALIGN);

    ~wxCustomisableToolBar();

    bool Create(wxWindow* parent, wxWindowID id, const wxPoint& pos = wxDefaultPosition, const wxSize& sz = wxDefaultSize,
        long style = wxTB_FLAT|wxTB_HORIZONTAL|wxTB_NODIVIDER|wxTB_NOALIGN);

    void Init();
    static void CleanUpMenu();

    void SetCustomisationName(const wxString& name) { m_customisationName = name; }
    const wxString& GetCustomisationName() const { return m_customisationName; }

    void SetExpandToFitParent(bool expand) { m_expandToFitParent = expand; }
    bool GetExpandToFitParent() const { return m_expandToFitParent; }

    void OnRightDown(wxMouseEvent& event);
    void OnCustomise(wxCommandEvent& event);

    virtual void DoSetSize(int x, int y,
                           int width, int height,
                           int sizeFlags = wxSIZE_AUTO);

    // For debugging purposes
    virtual void OnInternalIdle();

    wxString        m_customisationName;
    static wxMenu*  sm_menu;
    static long     sm_commandId; // customisation command id
    bool            m_expandToFitParent;
};

#endif
    // _WX_TOOLBARCUST_H_
